﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Abp.Reflection.Extensions;

namespace ARchGL.Platform.Web
{
    /// <summary>
    /// This class is used to find root path of the web project in;
    /// unit tests (to find views) and entity framework core command line commands (to find conn string).
    /// </summary>
    public static class WebContentDirectoryFinder
    {
        public static string CalculateContentRootFolder()
        {
            try
            {
                var coreAssemblyDirectoryPath = Path.GetDirectoryName(typeof(PlatformCoreModule).GetAssembly().Location);
                if (coreAssemblyDirectoryPath == null)
                {
                    throw new Exception("Could not find location of ARchGL.Platform.Core assembly!");
                }

                var directoryInfo = new DirectoryInfo(coreAssemblyDirectoryPath);
                while (!DirectoryContains(directoryInfo.FullName, "ARchGL.Platform.Web.sln"))
                {
                    if (directoryInfo.Parent == null)
                    {
                        //throw new Exception("Could not find content root folder!");
                        return string.Empty;
                    }

                    directoryInfo = directoryInfo.Parent;
                }

                var webMvcFolder = Path.Combine(directoryInfo.FullName, $"src{Path.DirectorySeparatorChar}ARchGL.Platform.Web.Mvc");
                if (Directory.Exists(webMvcFolder))
                {
                    return webMvcFolder;
                }

                var webHostFolder = Path.Combine(directoryInfo.FullName, $"src{Path.DirectorySeparatorChar}ARchGL.Platform.Web.Host");
                if (Directory.Exists(webHostFolder))
                {
                    return webHostFolder;
                }
            }
            catch (Exception )
            {
                return string.Empty;
            }

            throw new Exception("Could not find root folder of the web project!");
        }

        private static bool DirectoryContains(string directory, string fileName)
        {
            return Directory.GetFiles(directory).Any(filePath => string.Equals(Path.GetFileName(filePath), fileName));
        }

        /// <summary>
        /// 获取 wwwroot 所在目录
        /// </summary>
        /// <returns></returns>
        public static string GetContentRootFolder()
        {
            // 当前目录
            var dirInfo = new DirectoryInfo(Assembly.GetExecutingAssembly().GetDirectoryPathOrNull());

            // 向上查找包含wwwroot的目录
            while (!dirInfo.GetDirectories("wwwroot", SearchOption.AllDirectories).Any())
            {
                // 已经到根目录
                if (dirInfo.Parent == null) return null;
                dirInfo = dirInfo.Parent;
            }

            // wwwroot是当前目录的子目录
            if (dirInfo.GetDirectories("wwwroot").Any())
            {
                return dirInfo.FullName;
            }

            // 向下查找
            while (dirInfo != null)
            {
                foreach (var dir in dirInfo.GetDirectories())
                {
                    // 当前目录包含wwwroot子目录
                    if (dir.GetDirectories("wwwroot", SearchOption.AllDirectories).Any())
                    {
                        // wwwroot是当前目录的子目录
                        if (dir.GetDirectories("wwwroot").Any())
                        {
                            return dir.FullName;
                        }
                        dirInfo = dir;

                        break; // 继续查找其它子目录
                    }
                }
            }
            return null; // 未找到包含wwwroot的目录
        }

        /// <summary>
        /// 查找指定目录
        /// </summary>
        /// <param name="folder"></param>
        /// <returns></returns>
        public static string FindFolder(string folder)
        {
            var curDir = new DirectoryInfo(Assembly.GetExecutingAssembly().GetDirectoryPathOrNull());

            while (!curDir.GetDirectories(folder, SearchOption.AllDirectories).Any())
            {
                if (curDir.Parent == null)
                {
                    return null;
                }
                curDir = curDir.Parent;
            }

            if (curDir.GetDirectories(folder).Any())
            {
                return Path.Combine(curDir.FullName, folder);
            }

            while (curDir != null)
            {
                foreach (var subDir in curDir.GetDirectories())
                {
                    if (subDir.GetDirectories(folder, SearchOption.AllDirectories).Any())
                    {
                        if (subDir.GetDirectories(folder).Any())
                        {
                            return Path.Combine(subDir.FullName, folder);
                        }
                        curDir = subDir;

                        break;
                    }
                }
            }

            return null;
        }

    }
}
